#!/usr/bin/env python
#-*- coding:utf-8 -*-

"""
    PySeq0 - a python sequencer
    (c) by Tobias Sauer 2011
    Copyright: GPL v2 only
    http://leichtdio.de
    tobias@leichtdio.de
    
    Google Code:
    http://pyseq0.leichtdio.de
"""

import time
import logging
import pyportmidi.midi as pypm
pypm.init()

_log = logging.getLogger("Midi")

class MidiNote:
    """
        MidiNote kann Notennamen in MidiNotenNr umrechnen
    """
    def __init__(self):
        self.start = 60
        self.name = ("c", "c#", "d", "d#", "e", "f", "f#",
                     "g", "g#", "a", "a#", "b")

    def get_midi_nr (self, notename, octave=0):
        #Tuple startet mit der Zählung bei 0 (> 0 = 60)
        # ein Oktave -= 12
        notename = notename.lower()
        for org, anders in (("c#","db"), ("d#","eb"),  ("f#","gb"),
                            ("g#", "ab"), ("a#","bb")):
            if notename == anders:
                notename = org
        try:
            midinr = 60 + self.name.index(notename) + octave*12
        except ValueError:
            midinr = False
        return midinr

class MidiHandler:
    """
        handle all midi devices
    """
    def __init__ (self):
        self.devs = {}

    def update(self):
        #for port in self.devs:
        #    self.devs[port].close()
        pypm.quit()
        pypm.init()
        self.initall()

    def get_name(self, portnr):
        if pypm.get_device_info(portnr) != None:
            return pypm.get_device_info(portnr)[1]
        else:
            _log.debug("get_name: %s None", portnr)
            return None

    def get_midiport(self, midiname):
        for devnr in range(0, pypm.get_count()):
            if midiname == pypm.get_device_info(devnr)[1]:
                _log.info("AutoConnect %s to Port %s", midiname, devnr)
                return devnr

    def playnote(self, portnr, notedesc, duration):
        if notedesc[0] != "sleep":
            self.note_on(portnr, notedesc)
        time.sleep(duration / 1000.)
        if notedesc[0] != "sleep":
            self.note_off(portnr, notedesc[0:2])

    def note_on(self, portnr, notedesc):
        self.devs[portnr].note_on(*notedesc)

    def note_off(self, portnr, notedesc):
        self.devs[portnr].note_off(*notedesc)

    def initdev(self, portnr):
        if pypm.get_device_info(portnr)[3]:
            self.devs[portnr] = pypm.Output(portnr)
        else:
            _log.info("Port %s ist ein InputDev, nicht unterstützt", portnr)

    def initall(self):
        for portnr in range(pypm.get_count()):
            self.initdev(portnr)
        _log.debug("Devices: %s", self.devs)

    def searchport(self, name):
        ## @@ToDo: Schauen, ob es dafür ne Dict-Inline Funktion gibt! dict.haskey=PortNr 
        for portnr in self.devs:
            if self.devs[portnr].name == name:
                return portnr

    def __del__(self):
        _log.info("Closing devices")
        for portnr in self.devs:
            #self.devs[portnr].abort()
            self.devs[portnr] = None
        pypm.quit()

if __name__ == "__main__":
    debug = MidiHandler()
    debug.initall()
    #debug.get_mididevs()
    #debug.searchport("Specimen Sampler")
    #debug.close()
    #debug2 = MidiNote()
    #debug.initall()
    debug.playnote(14, (60, 127, 0), 5000)
    #raw_input()
